package com.netty.demo.server.dll;

import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.IntByReference;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * jna调用dll文件工具类
 * Java和C的数据类型对照表
 * Java 类型                      C 类型                  原生表现
 * boolean                      int                     32位整数(可定制) 
 * byte                         char                    8位整数
 * char                         wchar_t                 平台依赖
 * short                        short                   16位整数
 * int                          int                     32位整数
 * long                         long, __int64           64位整数
 * float                        float                   32位浮点数
 * double                       double                  64位浮点数
 * Buffer/Pointer               pointer                 平台依赖(32或64位指针)
 * <T>[] (基本类型的数组)         pointer/array            32或64位指针(参数/返回值)邻接内存(结构体成员)
 * String                       char*                    /0结束的数组 (native encoding or jna.encoding)
 *  WString                      wchar_t*                /0结束的数组(unicode)
 *  Structure                    struct* /struct          指向结构体的指针(参数或返回值)
 * Union                        union                   等同于结构体
 * Structure[]                   struct[]                结构体的数组，邻接内存
 * Callback                     <T> (*fp)()             Java函数指针或原生函数指针
 * NativeMapped                 varies                  依赖于定义
 * NativeLong                   long                    平台依赖(32或64位整数)
 * PointerType                  pointer                 和Pointer相同
 * <p>
 * 定义结构体
 *
 * @author 余秀良
 * @version 1.0
 * <p>  date: 2019 - 09 - 12  10:40    </p>
 * <p>  address: 四川成都  </p>
 */
public interface CallLibrary extends Library {

    /*
     * C++方法和Java对照例子
     *  C++                                           JAVA
     * method(struct DEMO demo)                method(DemoStructure.ByValue demo)
     * method(struct DEMO *demo)               method(DemoStructure.ByReference demo)
     * method(struct DEMO **demo)              method(DemoStructure.ByReference[] demo)
     * method(DEMO demo)                       method(Pointer demo)
     * method(DEMO *demo)                      method(PointerByReference demo)
     * method(DEMO **demo)                     method(PointerByReference[] demo)
     * method(char * data)                     method(char[] data)
     * method(const unsigned char* data)       method(char[] data)
     */

    /**
     * /dll文件路径加文件名   不需要写  .dll
     */
    CallLibrary CALL_LIBRARY = Native.load("C:\\Windows\\System32\\msvcrt", CallLibrary.class);

    /**
     * 模拟函数
     * <p>
     * 方法1
     *
     * @param byValue ByValue
     * @return int
     */
    int method(DemoStructure.ByValue byValue);

    /**
     * 方法1
     *
     * @param byReference    ByReference
     * @param intByReference IntByReference
     */
    void method(DemoStructure.ByReference byReference, IntByReference intByReference);

    /**
     * 方法1
     *
     * @param byReference ByReference
     * @return int
     */
    int method(DemoStructure.ByReference byReference);

    /**
     * 带回调函数的函数
     */
    int method(Callback callback, String name, int flag);

    void method(int a, int b, char[] data);

    String method(FloatByReference floatByReference, char[] outString);

    void method(DemoStructure.ByReference byReference, DemoStructure.ByValue byValue);


    void demo(DemoCallback callback);

    interface DemoCallback extends Callback {
        /**
         * 注意参数顺序需要保持一致
         */
        void invoke(Pointer val, int length);
    }

    class DemoCallbackImpl implements DemoCallback {
        @Override
        public void invoke(Pointer val, int length) {
            System.out.println("returned byte array, size: " + length);
            System.out.println("java mehtod, callback: " + Arrays.toString(val.getByteArray(0, length)));
        }
    }

    class DemoStructure extends Structure {
        /**
         * 公共字段的顺序，必须与C语言中的结构的顺序一致，否则会报错！
         */
        public int a;
        public int b;
        public int c;
        public int d;

        public DemoStructure() {
            super();
        }

        public DemoStructure(Pointer pointer) {
            super(pointer);
        }

        /**
         * 定义取值次序，需要与C/C++中对齐，不然会出现NoSuchFieldError
         *
         * @return List<String>
         */
        @Override
        protected List<String> getFieldOrder() {
            List<String> field = new ArrayList<>();
            field.add("a");
            field.add("b");
            field.add("c");
            field.add("d");
            return field;
        }

        /**
         * 涉及到结构体的传递，必须使用  ByReference 或者 ByValue 中的一种
         * 指针和引用的传递使用  ByReference
         * 结构体传指针
         */
        public static class ByReference extends DemoStructure implements Structure.ByReference {
        }

        /**
         * 拷贝参数传递使用 ByValue
         * 结构体传值
         */
        public static class ByValue extends DemoStructure implements Structure.ByValue {
        }
    }
}

